package com.relytosoft.mizar.media.analyze.services.controller.structure;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.exception.ServiceException;
import com.relytosoft.dubhe.common.core.object.ResponseResult;
import com.relytosoft.dubhe.common.core.utils.BeanCopyUtils;
import com.relytosoft.dubhe.common.core.utils.CommonUtils;
import com.relytosoft.dubhe.common.log.annotation.OpLog;
import com.relytosoft.dubhe.common.log.enums.OpTypeEnum;
import com.relytosoft.dubhe.common.satoken.entity.CurrentUser;
import com.relytosoft.mizar.media.analyze.api.entity.structure.AyStructureTask;
import com.relytosoft.mizar.media.analyze.api.entity.structure.AyStructureTaskSon;
import com.relytosoft.mizar.media.analyze.api.pojo.dto.AyStructureTaskDto;
import com.relytosoft.mizar.media.analyze.api.pojo.dto.AyStructureTaskUpdateDto;
import com.relytosoft.mizar.media.analyze.api.pojo.query.AyStructureTaskQuery;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.AyBatchVo;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.AyCameraVo;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.AyStructureTaskVo;
import com.relytosoft.mizar.media.analyze.services.service.structure.AyStructureTaskService;
import com.relytosoft.mizar.media.analyze.services.service.structure.AyStructureTaskSonService;
import com.relytosoft.mizar.media.common.enums.TaskStatusEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * StructureController
 *
 * @Author SunLi
 * @Date: 2022/5/19 11:51
 * @Version 1.0
 */
@RestController
@RequestMapping("analyze/structure/task")
@Api(tags = "结构化任务")
public class AyStructureTaskController {
    @Resource
    private AyStructureTaskService taskService;
    @Resource
    private AyStructureTaskSonService taskSonService;

    @SaCheckPermission("structure:task:insert")
    @OpLog(msg = "创建结构化分析任务", opType = OpTypeEnum.INSERT)
    @ApiOperation("创建结构化分析任务")
    @PostMapping({"/insert"})
    public ResponseResult<AyBatchVo> insert(@RequestBody AyStructureTaskDto ayStructureTaskDto) {

        if(ayStructureTaskDto.getStatus()!= TaskStatusEnum.NOT_STARTED.getValue() &&ayStructureTaskDto.getStatus()!=TaskStatusEnum.CREATED.getValue()){
            throw new ServiceException("任务状态只能为启动或不启动！");
        }
        if(ayStructureTaskDto.getAyCameraVos().isEmpty()){
            throw new ServiceException("任务通道不能为空！");
        }
        //所有需要添加的设备id
        List<AyCameraVo> ayCameraVos = ayStructureTaskDto.getAyCameraVos();
        if(!validateCamera(ayCameraVos)){
            throw new ServiceException("任务通道参数不完整！");
        }

        AyBatchVo ayBatchVo = new AyBatchVo();
        ayBatchVo.setTotal(ayCameraVos.size());
        //没有符合条件的设备
        if (!taskService.addFrontVerify(ayStructureTaskDto)) {
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ayCameraVos.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("所选设备均已有未删除的分析任务，请检查"));
            return ResponseResult.ok(ayBatchVo);
        }
        //构造主任务
        AyStructureTask task = AyStructureTaskDto.buildAddTask(ayStructureTaskDto);
        List<AyStructureTaskSon> taskSonList= taskService.buildTaskSon(ayStructureTaskDto);

        //创建分析任务
        boolean insertResult= taskService.insertTaskWithSonWith(task, taskSonList);
        if(insertResult){
            ayBatchVo.setSuccess(taskSonList.size());
            ayBatchVo.setError(ayCameraVos.size() - taskSonList.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("符合条件的任务已添加成功"));

            //任务创建时 状态为 启动
            if(task.getStatus()==TaskStatusEnum.CREATED.getValue()){
                //发送EMQ消息
                taskSonList.forEach(a->taskSonService.sendInsertTaskMsg(a));
            }
        }
        else{
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ayCameraVos.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("任务添加失败"));
        }
        return ResponseResult.ok(ayBatchVo);
    }

    @SaCheckPermission("structure:task:list")
    @OpLog(msg = "查询结构化分析任务列表", opType = OpTypeEnum.SELECT)
    @ApiOperation("查询结构化分析任务列表")
    @GetMapping({"/list"})
    public ResponseResult<Map<String, Object>> select(AyStructureTaskQuery ayStructureTaskQuery, PageQuery pageQuery) {
        IPage<AyStructureTaskVo> page = taskService.selectAyStructureTaskPageList(pageQuery, ayStructureTaskQuery);
        return ResponseResult.ok(CommonUtils.getPageData(page));
    }

    @SaCheckPermission("structure:task:update")
    @OpLog(msg = "修改结构化分析任务", opType = OpTypeEnum.UPDATE)
    @ApiOperation("修改结构化分析任务")
    @PutMapping({"/update"})
    public ResponseResult<Void> update(@RequestBody AyStructureTaskUpdateDto ayStructureTaskUpdateDto) {
        AyStructureTask ayStructureTask= taskService.getById(ayStructureTaskUpdateDto.getId());
        if(ayStructureTask==null){
            return ResponseResult.fail("任务不存在！");
        }
        //验证任务状态是否可修改
        if(ayStructureTask.getStatus()!=TaskStatusEnum.NOT_STARTED.getValue()&&ayStructureTask.getStatus()!=TaskStatusEnum.FINISHED.getValue())
        {
            //任务状态不为未启动、已结束时，不允许修改
            return ResponseResult.fail("任务不允许修改！");
        }
        AyStructureTask entity= BeanCopyUtils.copy(ayStructureTaskUpdateDto, AyStructureTask.class);

        boolean result = taskService.updateById(entity);
        if (result) {
            //批量更新子任务名称
            taskService.updateSonTaskName(entity.getId(),entity.getName());
            return ResponseResult.ok();
        }
        return ResponseResult.fail("任务更新失败！");
    }

    @SaCheckPermission("structure:task:delete")
    @OpLog(msg = "删除结构化分析任务", opType = OpTypeEnum.DELETE)
    @ApiOperation("删除结构化分析任务")
    @PutMapping({"/delete"})
    public ResponseResult<Void> delete(@RequestBody List<Integer> ids) {
        //构造可删除的任务
        List<AyStructureTask> deleteTaskList= taskService.buildDeleteTask(ids);
        if(ArrayUtil.isNotEmpty(deleteTaskList)){
            taskService.deleteTaskTrans(ids,deleteTaskList);
            return ResponseResult.ok("已删除符合条件的任务");
        }
        else{
            return ResponseResult.fail("没有符合删除条件的任务");
        }
    }

    @SaCheckPermission("structure:task:start")
    @OpLog(msg = "启动结构化分析任务", opType = OpTypeEnum.OTHER)
    @ApiOperation("启动结构化分析任务")
    @PostMapping({"/start"})
    public ResponseResult<AyBatchVo> start(@RequestBody List<Integer> ids) {
        if (ids.isEmpty()) {
            throw new ServiceException("请选择需要启动的任务！");
        }
        AyBatchVo ayBatchVo = new AyBatchVo();
        ayBatchVo.setTotal(ids.size());
        //启动任务前置验证
        if(!taskService.startTaskFrontVerify(ids)){
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ids.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("没有符合条件的任务"));
            return ResponseResult.ok(ayBatchVo);
        }
        //获取可启动的子任务
        List<AyStructureTaskSon> taskSonList=taskService.selectCanStartTaskSonList(ids);
        if(taskSonList.isEmpty()){
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ids.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("没有符合条件的任务"));
            return ResponseResult.ok(ayBatchVo);
        }
        //待启动的主任务
        List<Integer> newIds= taskSonList.stream().map(AyStructureTaskSon::getStructureTaskId).collect(Collectors.toList());
        ids =newIds.stream().distinct().collect(Collectors.toList());
        Integer succ=0;
        for(Integer id :ids) {
            //待启动的子任务
            List<AyStructureTaskSon> deleteTaskSons = new ArrayList<>();
            List<AyStructureTaskSon> insertTaskSons = new ArrayList<>();
            List<AyStructureTaskSon> startTaskSons = new ArrayList<>();
            List<AyStructureTaskSon> currentTaskSons=taskSonList.stream().filter(item-> Objects.equals(item.getStructureTaskId(), id)).collect(Collectors.toList());

            taskSonService.buildDeleteAndStartTaskSon(currentTaskSons,deleteTaskSons,insertTaskSons);
            taskSonService.buildStartTaskSon(currentTaskSons,startTaskSons);

            AyStructureTask ayStructureTask=new AyStructureTask();
            ayStructureTask.setId(id);
            ayStructureTask.setStatus(TaskStatusEnum.CREATED.getValue());

            try {
                //启动任务处理
                if(taskService.startTaskWithSon(ayStructureTask,deleteTaskSons,insertTaskSons,startTaskSons)){
                    succ++;
                    if(!insertTaskSons.isEmpty()){
                        //发送消息
                        insertTaskSons.stream().forEach(a->taskSonService.sendInsertTaskMsg(a));
                    }
                    if(!startTaskSons.isEmpty()){
                        //发送消息
                        startTaskSons.stream().forEach(a->taskSonService.sendInsertTaskMsg(a));
                    }
                }
            }
            catch (Exception ex){
            }
        }
        ayBatchVo.setSuccess(succ);
        ayBatchVo.setError(ayBatchVo.getTotal()-ayBatchVo.getSuccess());
        ayBatchVo.setErrorMsg(Collections.singletonList("符合条件的任务已启动成功"));
        return ResponseResult.ok(ayBatchVo);
    }

    @SaCheckPermission("structure:task:stop")
    @OpLog(msg = "停止结构化分析任务", opType = OpTypeEnum.OTHER)
    @ApiOperation("停止结构化分析任务")
    @PostMapping({"/stop"})
    public ResponseResult<AyBatchVo> stop(@RequestBody List<Integer> ids) {
        if (ids.isEmpty()) {
            throw new ServiceException("请选择需要启动的任务！");
        }
        AyBatchVo ayBatchVo = new AyBatchVo();
        ayBatchVo.setTotal(ids.size());
        //停止任务前置验证
        if(!taskService.stopTaskFrontVerify(ids)){
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ids.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("没有符合条件的任务"));
            return ResponseResult.ok(ayBatchVo);
        }
        //获取待停止的子任务
        List<AyStructureTaskSon> taskSonList=taskService.selectCanStopTaskSonList(ids);
        if(ArrayUtil.isEmpty(taskSonList)){
            ayBatchVo.setSuccess(0);
            ayBatchVo.setError(ids.size());
            ayBatchVo.setErrorMsg(Collections.singletonList("没有符合条件的任务"));
            return ResponseResult.ok(ayBatchVo);
        }

        //待停止的主任务
        List<Integer> newIds =taskSonList.stream().map(AyStructureTaskSon::getStructureTaskId).collect(Collectors.toList());
        Integer succ=0;
        for (Integer id :newIds){

            List<AyStructureTaskSon> stopTaskSons = new ArrayList<>();
            List<AyStructureTaskSon> currentTaskSons=taskSonList.stream().filter(item-> Objects.equals(item.getStructureTaskId(), id)).collect(Collectors.toList());
            taskSonService.buildStopTaskSon(currentTaskSons,stopTaskSons);

            AyStructureTask ayStructureTask=new AyStructureTask();
            ayStructureTask.setId(id);
            ayStructureTask.setStatus(TaskStatusEnum.FINISHED.getValue());
            ayStructureTask.setUpdatedBy(CurrentUser.getCurrentUserFullName());
            ayStructureTask.setUpdatedId(CurrentUser.getCurrentUserId());
            ayStructureTask.setEndTime(LocalDateTime.now());

            try {
                //停止任务处理
                if(taskService.stopTaskWithSon(ayStructureTask,stopTaskSons))
                {
                    succ++;

                    //发送删除任务消息
                    for (AyStructureTaskSon taskSon:stopTaskSons){
                        if(StrUtil.isNotEmpty(taskSon.getTaskId())){
                            taskSonService.sendDeleteTaskMsg(taskSon.getTaskId());
                        }
                    }
                }
            }
            catch (Exception ex){
                ex.printStackTrace();
            }
        }
        ayBatchVo.setSuccess(succ);
        ayBatchVo.setError(ayBatchVo.getTotal()-ayBatchVo.getSuccess());
        ayBatchVo.setErrorMsg(Collections.singletonList("符合条件的任务已停止成功"));

        return ResponseResult.ok(ayBatchVo);
    }

    @SaCheckPermission("structure:task:list")
    @ApiOperation("任务选择列表")
    @GetMapping({"/selectlist"})
    public ResponseResult list() {
        return ResponseResult.ok(taskService.selectTaskList());
    }

    private boolean validateCamera(List<AyCameraVo> cameraVos){
        if(cameraVos.isEmpty()){
            return false;
        }
        for(AyCameraVo cameraVo:cameraVos){
            if(StrUtil.isEmpty(cameraVo.getCameraId())||StrUtil.isEmpty(cameraVo.getCameraName())||StrUtil.isEmpty(cameraVo.getVideoUrl())){
                return false;
            }
        }
        return true;
    }
}
